package de.morris;

import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.swing.JFrame;
import javax.vecmath.Matrix3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.universe.SimpleUniverse;


public class Start extends JFrame implements MouseListener, KeyListener {
	Canvas3D eineZeichenflaeche;
	SimpleUniverse universum;
	com.sun.j3d.utils.picking.PickCanvas pick;
	OrbitBehavior orbit;
	flyingCamera cam;
	public float clippingPlane;
	
	BranchGroup bg1 = new BranchGroup();
	TransformGroup tRoot = new TransformGroup();
	TransformGroup tRootBubbles = new TransformGroup();
	TransformGroup figure = new TransformGroup();
	TransformGroup dest = new TransformGroup();
	
	boolean first = true;
	boolean viewChange = false;
	boolean runningGame = false;
	

	public Start(String pl1, String pl2) {
		
		if (pl1 == null){
			pl1 = "Player1";
		}
		if (pl2 == null){
			pl2 = "Player2";
		}
		
		getContentPane().setLayout(new BorderLayout());
		GraphicsConfiguration eineKonfiguration = SimpleUniverse.getPreferredConfiguration();
		eineZeichenflaeche = new Canvas3D(eineKonfiguration);
		getContentPane().add("Center", eineZeichenflaeche);
		universum = new SimpleUniverse(eineZeichenflaeche);
		eineZeichenflaeche.getView();
		universum.getViewingPlatform().setNominalViewingTransform();

		CameraStuff();
		
		AddObjects(pl1, pl2);

		 pick = new com.sun.j3d.utils.picking.PickCanvas(eineZeichenflaeche, bg1);
		 pick.setMode(com.sun.j3d.utils.picking.PickCanvas.GEOMETRY);
		 eineZeichenflaeche.addMouseListener(this);
		 eineZeichenflaeche.addKeyListener(this);

		 setSize(800,800);
		 setVisible(true);
	}
	
	public void AddObjects(String pl1, String pl2){
		 tRoot.addChild(new de.Objects.createFigures());
		 tRootBubbles.addChild(new de.Objects.createBubbles());
		 bg1.addChild(tRoot);
		 bg1.addChild(tRootBubbles);
		 bg1.compile();
		 universum.addBranchGraph(bg1);
		 universum.addBranchGraph(new de.Objects.Housing());
		 universum.addBranchGraph(new de.Objects.Spielbrett(pl1, pl2));
		 universum.addBranchGraph(new de.Objects.soroundingWorld());
		 universum.addBranchGraph(new de.Objects.createMills());
	}
	
	public void CameraStuff(){
		
		View view = universum.getViewer().getView();
		view.setBackClipDistance(500);
		// Kamera
		Transform3D Camera = new Transform3D();
		Camera.setTranslation(new Vector3f(0.0f,100.0f,500.0f));
		universum.getViewingPlatform().getViewPlatformTransform().setTransform(Camera);

		
		// Kamera per Maus drehen
		BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 2000.0);
		
		orbit = new OrbitBehavior(eineZeichenflaeche,	OrbitBehavior.REVERSE_ALL);
		
		// faster or slower zooming/shifting/rotating
		orbit.setTransFactors(2.0f, 2.0f);
		orbit.setZoomFactor(5.0f);
//		orbit.setRotateEnable(false);
		
		// Bounds for the behavior
		orbit.setSchedulingBounds(bounds);
		universum.getViewingPlatform().setViewPlatformBehavior(orbit);
		
		cam = new flyingCamera(universum.getViewingPlatform().getViewPlatformTransform());
		bg1.addChild(cam);
	
		// Get the camera in start position
		Point3f pos2 = new Point3f(0.0f,100.0f,500.0f);
		Matrix3f rot2 = new Matrix3f();
		cam.move(pos2, rot2,3000);
	}
	
	public void addExitListener(){
		this.addWindowListener( new WindowAdapter() {
	          public void windowClosing( WindowEvent e ) { 
	        	  System.exit(0);
	          }
		});	
	}

	@Override
	public void mouseClicked(MouseEvent e) {	
		pick.setShapeLocation(e);
		PickResult res = pick.pickClosest();
		if (res == null) {
			if (runningGame == false){
				PerformFirstCamera();
				runningGame = true;
			}
		} else {
			TransformGroup t = (TransformGroup) res.getNode(PickResult.TRANSFORM_GROUP);
			Primitive p = (Primitive) res.getNode(PickResult.PRIMITIVE);
			t.setUserData(p.getUserData());
			JumpTo(t);
		}		
	}
	
	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
	}

	@Override
	public void mouseReleased(MouseEvent e) {
	}
	
	public void JumpTo(TransformGroup t){
		Point3f pos2 = new Point3f();
		Matrix3f rot2 = new Matrix3f();
		
		if (t.getUserData() == null){
			figure = t;
		} else if (t.getUserData() == "SWITCH"){
			if (viewChange == false){
				pos2 = new Point3f(0.0f,15.0f,-15.0f);
				Transform3D rot1 = new Transform3D();
				rot1.rotX(Math.PI/-1.35);	
				Transform3D rot4 = new Transform3D();
				rot4.rotZ(Math.PI/-1.001);
				rot1.mul(rot4);
				rot1.getRotationScale(rot2);
				viewChange = true;
			} else {
				pos2 = new Point3f(0.0f,15.0f,15.0f);
				Transform3D rot1 = new Transform3D();
				rot1.rotX(Math.PI/-3.75);	
				Transform3D rot4 = new Transform3D();
				rot4.rotZ(Math.PI/-0.001);
				rot1.mul(rot4);
				rot1.getRotationScale(rot2);
				viewChange = false;
			}
			cam.move(pos2, rot2, 1000);
		} else {
			dest = t;
			Transform3D tryTrans = (Transform3D) dest.getUserData();
			tryTrans.setScale(0.3);
			figure.setTransform(tryTrans);		
		}
		
	}

	public void PerformFirstCamera(){
		Matrix3f rot2 = new Matrix3f();
		Point3f pos3 = new Point3f(0.0f,15.0f,15.0f);
		Matrix3f rot3 = new Matrix3f();
		Transform3D rota = new Transform3D();
		rota.rotX(Math.PI/-3.75);
		rota.getRotationScale(rot2);
		cam.move(pos3, rot2, 3000);
		
		// faster or slower zooming/shifting/rotating
		orbit.setTransFactors(0.0f, 0.0f);
		orbit.setZoomFactor(0.0f);
		orbit.setRotateEnable(true);
	}

	
	@Override
	public void keyPressed(KeyEvent e) {
	}
	

	@Override
	public void keyReleased(KeyEvent e) {
	}
	

	@Override
	public void keyTyped(KeyEvent e) {
		Point3f pos2 = new Point3f();
		Matrix3f rot2 = new Matrix3f();
		
		char key = e.getKeyChar();
		switch (key){
			case '1':
				pos2 = new Point3f(0.0f,15.0f,-15.0f);
				Transform3D rot1 = new Transform3D();
				rot1.rotX(Math.PI/-1.35);	
				Transform3D rot4 = new Transform3D();
				rot4.rotZ(Math.PI/-1.001);
				rot1.mul(rot4);
				rot1.getRotationScale(rot2);
				cam.move(pos2, rot2, 1000);
				viewChange = true;
				runningGame = true;
				orbit.setTransFactors(0.0f, 0.0f);
				orbit.setZoomFactor(0.0f);
				orbit.setRotateEnable(true);
				break;
			case '2':
				pos2 = new Point3f(0.0f,15.0f,15.0f);
				Transform3D rot5 = new Transform3D();
				rot5.rotX(Math.PI/-3.75);	
				Transform3D rot6 = new Transform3D();
				rot6.rotZ(Math.PI/-0.001);
				rot5.mul(rot6);
				rot5.getRotationScale(rot2);
				cam.move(pos2, rot2, 1000);
				viewChange = false;
				runningGame = true;
				orbit.setTransFactors(0.0f, 0.0f);
				orbit.setZoomFactor(0.0f);
				orbit.setRotateEnable(true);
				break;
			case '3':
				pos2 = new Point3f(0.0f,100.0f,500.0f);
				rot2 = new Matrix3f();
				cam.move(pos2, rot2, 3000);
				runningGame = false;
				// faster or slower zooming/shifting/rotating
				orbit.setTransFactors(2.0f, 2.0f);
				orbit.setZoomFactor(5.0f);
				break;
			default:
				System.out.println("Falsche Eingabe");
				break;
		}

	}
}